﻿using UnityEngine;

namespace Yoozoo.Modules.CarScene
{
    public class RotateCamera : MonoBehaviour
    {
        /// <summary>
        ///     UI画出的允许拖动范围
        /// </summary>
        private RectTransform allowArea;

        [TextArea(12, 18)] 
        public string Info = "结构\n" +
                            "CameraRoot (与目标位置保持一致, 一般是目标的底面中心点)\n" +
                            "   + LookAt (观察目标的位置, 如头顶上方, 可以任意调整位置)\n" +
                            "     + Rotate (旋转, 可以调整Y轴旋转)\n" +
                            "       + Pitch (俯仰, 可以调整X轴旋转)\n" +
                            "         + Zoom (远近, 可以调整Z轴距离)";
        public float RotateSensibility = 1;

        public Vector2 PitchRange;

        public float PitchSensibility = 1;

        public Vector2 ZoomRange;

        public float ZoomSensibility = 1;

        private bool isMouseDown;

        private Vector3 lastMousePosition;

        private int layerUI;

        private Camera uiCamera;
        
        public Transform LookAt { get; private set; }

        public Transform Rotate { get; private set; }

        public Transform Pitch { get; private set; }

        public Transform Zoom { get; private set; }

        /// <summary>
        ///     旋转指定角度
        /// </summary>
        /// <param name="deltaAngle"></param>
        public void RotateBy(float deltaAngle)
        {
            Rotate.Rotate(0, deltaAngle, 0);
        }

        /// <summary>
        ///     旋转到指定角度
        /// </summary>
        /// <param name="angle"></param>
        public void RotateTo(float angle)
        {
            Rotate.localEulerAngles = new Vector3(0, angle, 0);
        }

        /// <summary>
        ///     获取镜头旋转角度
        /// </summary>
        /// <returns></returns>
        public float GetRotate()
        {
            return Rotate.localEulerAngles.y;
        }

        /// <summary>
        ///     倾斜指定角度
        /// </summary>
        /// <param name="deltaAngle"></param>
        public void PitchBy(float deltaAngle)
        {
            float angle = Pitch.localEulerAngles.x + deltaAngle;
            PitchTo(angle);
        }

        /// <summary>
        ///     倾斜到指定角度
        /// </summary>
        /// <param name="angle"></param>
        public void PitchTo(float angle)
        {
            angle = Mathf.Clamp(angle, PitchRange.x, PitchRange.y);
            Pitch.localEulerAngles = new Vector3(angle, 0, 0);
        }

        /// <summary>
        ///     拉进镜头
        /// </summary>
        /// <param name="deltaDistance"></param>
        public void ZoomBy(float deltaDistance)
        {
            var distance = Zoom.localPosition.z + deltaDistance;
            ZoomTo(distance);
        }

        /// <summary>
        ///     拉进镜头到指定距离
        /// </summary>
        /// <param name="distance"></param>
        public void ZoomTo(float distance)
        {
            distance = Mathf.Clamp(distance, ZoomRange.x, ZoomRange.y);
            Zoom.localPosition = new Vector3(0, 0, distance);
        }

        private void Start()
        {
            LookAt = transform.Find("LookAt");
            Rotate = transform.Find("LookAt/Rotate");
            Pitch = transform.Find("LookAt/Rotate/Pitch");
            Zoom = transform.Find("LookAt/Rotate/Pitch/Zoom");
            layerUI = LayerMask.NameToLayer("UI");
        }

        private void Update()
        {
            if (isMouseDown)
            {
                if (Input.GetMouseButton(0))
                {
                    var x = Input.mousePosition.x - lastMousePosition.x;
                    var y = Input.mousePosition.y - lastMousePosition.y;
                    RotateBy(x * RotateSensibility);
                    PitchBy(y * PitchSensibility);
                    lastMousePosition = Input.mousePosition;
                }
                else
                {
                    isMouseDown = false;
                }
            }
            else
            {
                if (Input.GetMouseButtonDown(0))
                {
                    if (allowArea)
                        if (!RectTransformUtility.RectangleContainsScreenPoint(allowArea, Input.mousePosition, uiCamera))
                            return;

                    isMouseDown = true;
                    lastMousePosition = Input.mousePosition;
                }
            }

            ZoomBy(Input.GetAxis("Mouse ScrollWheel") * ZoomSensibility);
        }

        public void SetAllowArea(RectTransform allowArea, Camera uiCamera)
        {
            this.allowArea = allowArea;
            this.uiCamera = uiCamera;
        }
    }
}
